#include "list.h"

NODE *elements_root;
NODE *current_elem;
NODE_DATA *nodes_root;
G2NODE_DATA *g2nodes_root;

//all around
void list_init() 
{
	elements_root = NULL;
	nodes_root = NULL;
	g2nodes_root = NULL;
}

void list_destroy()
{
	NODE *n;
	for(n = elements_root; n != NULL; n = n->nxt)
		free(n);

	NODE_DATA *nd;
	for(nd = nodes_root; nd != NULL; nd = nd->nxt)
		free(nd);

	G2NODE_DATA *g;
	for(g = g2nodes_root; g != NULL; g = g->nxt)
		free(g);
}


//ELEMENTS
void list_get_next_element_init() 
{
	current_elem = elements_root;
}

int list_hasElement_name(char *name)
{
	char *search_name;	
	
	search_name = strdup(name);	
	tokenizer_strtoupper(&search_name);
		
	return(list_hasElement_hashcode(hash_djb2(search_name)));
}

int list_hasElement_hashcode(unsigned long hashcode)
{
	NODE *n;
	for(n = elements_root; (n != NULL) && (n->hashcode != hashcode); n = n->nxt);
	
	return (n != NULL);
}

void list_insert_element(char type, unsigned long hashcode, void **data)	//TODO FIFO also
{
	NODE *n;
	n = (NODE *)malloc(sizeof(NODE));
	
	n->type = type;
	n->hashcode = hashcode;
	n->data = *data;
	
	
	n->nxt = elements_root;
	elements_root = n;
}

void list_get_next_element(NODE **n)
{
	*n = current_elem;
	if(current_elem != NULL)
		current_elem = current_elem->nxt;	
	
}


//NODES
void list_insert_node(char *name, int id, int g_id)	
{
	NODE_DATA *n;  
	n = (NODE_DATA *)malloc(sizeof(NODE_DATA));
	
	n->name = strdup(name);
	n->id = id;
	n->g_id = g_id;	

	n->nxt = nodes_root;
	nodes_root = n;

	n->value = 0.0;
	n->print_flag = 0;
}

void list_modify_node_value(int id,double new_val)	//MNA writes the final value	
{
	NODE_DATA *n;
	for(n = nodes_root; (n != NULL) && (n->id != id); n = n->nxt);
	if(n != NULL)
		n->value = new_val;
	//printf("(%s)[%d] -> %f\n",n->name, n->id, n->value);
}

void list_node_print_flag (char *usr_print_node)
{
	char *name = strdup(usr_print_node);	
	NODE_DATA *n;

	if (!strcmp(name, "0")){
		for(n = nodes_root; n != NULL; n = n->nxt)
			n->print_flag = 1;
	}
	else{			
		for(n = nodes_root; (n != NULL) && (strcmp(n->name,name)); n = n->nxt);
		if(n != NULL)
			n->print_flag = 1;
	}
}


int list_node_exists(int node)
{
	NODE_DATA *n;
	for(n = nodes_root; (n != NULL) && (n->id != node); n = n->nxt);
	
	return (n != NULL);
}


void list_print_nodes() 
{
	NODE_DATA *n;
	for(n = nodes_root; n != NULL; n = n->nxt)
		if(n->print_flag){
			printf("(%s) ",n->name);
			//printf("%d\n",n->id);
			printf("%f\n",n->value);
		}
		
}


//G2NODES
void list_insert_g2node(char *name, int id)	
{
	G2NODE_DATA *n;  
	n = (G2NODE_DATA *)malloc(sizeof(G2NODE_DATA));
	
	n->name = strdup(name);
	n->id = id;
	
	n->nxt = g2nodes_root;
	g2nodes_root = n;

	n->value = 0.0;
	n->print_flag = 0;
}

void list_modify_g2node_value(int id,double new_val)	//MNA writes the final value	
{
	G2NODE_DATA *n;
	for(n = g2nodes_root; (n != NULL) && (n->id != id); n = n->nxt);
	
	if(n != NULL)
		n->value = new_val;
	//printf("(%s)[%d] -> %f\n",n->name, n->id, n->value);
}

int list_g2node_exists(int node)
{
	G2NODE_DATA *n;
	for(n = g2nodes_root; (n != NULL) && (n->id != node); n = n->nxt);
	
	return (n != NULL);
}

void list_g2node_print_flag (char *usr_print_node)
{
	char *name = strdup(usr_print_node);	
	G2NODE_DATA *n;

	if (!strcmp(name, "0")){
		for(n = g2nodes_root; n != NULL; n = n->nxt)
			n->print_flag = 1;
	}
	else{			
		for(n = g2nodes_root; (n != NULL) && (strcmp(n->name,name)); n = n->nxt);
		if(n != NULL)
			n->print_flag = 1;
	}
}


void list_print_g2nodes() 
{
	G2NODE_DATA *g;

	for(g = g2nodes_root; g != NULL; g = g->nxt)
		if(g->print_flag){
			printf("(%s) ",g->name);
			//printf("%d\n",n->id);
			printf("%f\n",g->value);	
		}
}


void list_assign_final_values(int N, int n, double *x)
{
	//(int id,double new_val) Psaxno me vasi to ID tou node opote osa SWAPS kai na exoun ginei den me endiaferei!
	int j,k;	
	//g1	
	for(k = 1; k < N; ++k)
		list_modify_node_value(k, x[k-1]);	
	//g2
	for(j = 0; k <= n; ++k, ++j)
		list_modify_g2node_value(j, x[k-1]);
}
